#ifndef  __CPART_H__        // Begin 'include-guard' block.
#define  __CPART_H__        // (See #endif at the very end of this file).

//==============================================================================
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_
//                               (why all the numbers? I prefer 80-column text)
//
//      CPart.h   our Single Particle class;
//          'state-vectors' in CPartSys == dyn. alloc'd arrays of CPart objects
//                       See bottom of CPartSys.h for detailed explanation.
//==============================================================================

// CPart::partType values;
//-------------------------------
// a) Specifies how to draw/render each individual particle (CPart object), and
// b) gives you an easy way to enable/disable each particle:
//      partType >0 == active; partType < 0 == temporarily disabled.
//      Just reverse the sign of CPart::partType to enable/disable an object.
// (an easier/faster way to vary the number of particles without resorting to
//  memory allocation/de-allocation.  Also useful for debugging).
#define PTYPE_DEAD      0   // DEAD PARTICLE!!!  Abandoned, not in use, no
                            // meaningful values, available for re-use.
#define PTYPE_ALIVE     1   // 'default' particle; generic drawing
#define PTYPE_DUST      2   // Tiny dust-like particle
#define PTYPE_BALL      3   // Big bouncy round shiny sphere particle
#define PTYPE_STREAK    4   // Streak-like particle; rendered as GL_LINES using
                            // current and previous positions (fireworks, etc)
#define PTYPE_SPRITE    5   // Rendered as RGBA 'sprite'; a transparent little
                            // 2D picture, e.g. blurry splat for snow, smoke,etc
#define PTYPE_BLOBBY    6   // Render using Blinns' 'Blobby Implicits'--a blob
                            // that merges with neighbors to look like water...
#define PTYPE_MAXVAR    7   // Number of CPart particle types available.


// Particle member names
//------------------------
// Indices for the 'val[]' array inside each CPart particle object:
#define PART_MASS       0   // mass         (all particles have this)
#define PART_XPOS       1   //  position    (all particles have this)
#define PART_YPOS       2
#define PART_ZPOS       3
#define PART_XVEL       4   //  velocity    (all particles have this)
#define PART_YVEL       5
#define PART_ZVEL       6
#define PART_X_FTOT     7   // force accumulator: 'ApplyForces()' fcn sets these
#define PART_Y_FTOT     8   // to zero, then adds in each force to each particle.
#define PART_Z_FTOT     9
// Optional;
#define PART_CHARGE    10   // for electrostatic repulsion/attraction
#define PART_AGE       11   // # of frame-times since creation/initialization
// More Optional:
#define PART_MASS_VEL  12   // time-rate-of-change of mass.
#define PART_MASS_FTOT 13   // force-accumulator for mass-change
#define PART_R         14   // color : red
#define PART_G         15   // color : green
#define PART_B         16   // color : blue
#define PART_R_VEL     17   // time-rate-of-change of color:red
#define PART_G_VEL     18   // time-rate-of-change of color:grn
#define PART_B_VEL     19   // time-rate-of-change of color:blu
#define PART_R_FTOT    20   // force-accumulator for color-change: red
#define PART_G_FTOT    21   // force-accumulator for color-change: grn
#define PART_B_FTOT    22   // force-accumulator for color-change: blu
//
#define PART_MAXVAR    23   // Size of array in CPart uses to store its values.

//==============================================================================
// Declares a class for objects that each describe one complete single particle.
// (The CPartSys class defines 'state' as an array of CPart objects).
// The simplest possible particle object contains member variables for:
//      mass, position, velocity, forceAccumulator,
// but you can add other descriptors, including color, age, direction, and even
// emotional and behavioral variables such as fear, hunger, wing position etc.
//
// Rather than use individually-named member variables (e.g. position, velocity,
// mass, color, etc.), the CPart puts all of them in one single array called
// 'val[]', so that we can select any element by a numerical index.
//      Why?
// because the list of names may lengthen and change as we try new types of
// particles (fire, cloth, smoke, leaves, boids, water) with new behaviors.
// If we write code that accesses them by name (e.g. make state variables and
// their derivatives, use Euler, mid-point, and implicit solvers), then *all*
// of that code must change if we add or remove variables from CPart.  If we
// use an array, then:
//      --adding new variables just means we increase the array size;
//      --we can just collect arrays to make the complete current 'state vector'
//           s0 (see CPartSys class)
//      --we can use the same-sized arrays to make state vector derivative s0dot,
//      --we can define basic math operators on them: s1 = s0 + timestep*s0dot
//
//  OK: then which element should hold which variable?
// We COULD assign meaningful names to those array elements using a series of
// #define statements:
//      #define JT_XPOS 0
//      #define JT_YPOS 1
//      #define JT_ZPOS 2
//      #define JT_XVEL 3
//      #define JT_YVEL 4   ... etc.,
// If I do this, I must ensure the #define literals are sequential and unique,
// and I must be sure the val[] array size is correct.
// However, you may wish to use C/C++'s 'enum' facility, where you can define a
// type 'partT' that replaces those tedious-to-maintain #define statements with
// a simple list of variable names. If I declare an index variable of type
// 'partT', then I can choose the variable I want using those names, like this:
//      CPart mypart;      // declare a particle object;
//      partT indx;        // declare a partT variable (an enumerated type)
//      indx =yvel;        // sets indx value to 4;
//      //EACH of these statements has the same effect:
//      mypart.val[4] = 12.3;           // set val array's element 4;
//      mypart.val[indx] = 12.3;        // set val array's element 4;
//      mypart.val[indx = yvel] = 12.3; // set indx to 4, set val array's...
class CPart
{
public:
    int partType;           // Particle type; not required, but a) helps you
                            // identify the intended purpose of each particle,
                            // and b) gives you an easy way to enable/disable
                            // each particle:
                            //  partType  >0 == active particle; use it! the
                            //                 value describes its use
                            //  partType ==0 == 'dead' particle, abandoned,
                            //                  ignored, available for re-use.
                            //  partType  <0 == temporarily disabled 'frozen';
                            //                  to re-enable this particle,
                            //                  set partType = -partType;
    double val[PART_MAXVAR];// all particle parameters held in one big array.
                            // Why do this?
                            //  -usable as part of a 'state' vector,
                            //  -lets you select parameter by index number;
                            //  -if your index variable is type 'partT', then
                            //    you can also select the variables by name;
                            //  -To modify the list of variables in a particle,
                            //    just change the typedef for the 'partT' type.


    CPart(void);                // default constructor, destructor
    ~CPart(void);

};

#endif //end of #ifndef  __CPART_H__ include guard
